package com.xy.hms.util;

import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.util.concurrent.TimeUnit;

/**
 * @author xiaye
 * @create 2020-05-21-16:42
 */
@Component
@Aspect
@Slf4j
public class RedisCacheAspect {

    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 定义切入点，只要是使用rediscache的方法的都是切入点
     */
    @Pointcut("@annotation(RedisCache)")
    public void redisServicePoint() {

    }

    /**
     * 环绕通知，方法拦截器
     */
    @Around("redisServicePoint()")
    public Object WriteReadFromRedis(ProceedingJoinPoint point) {
        log.info("<====== 进入 redisCache 环绕通知 ======>");

        try {


            //获取切入点的方法签名
            MethodSignature signature = (MethodSignature) point.getSignature();
            RedisCache annotation = signature.getMethod().getAnnotation(RedisCache.class);

            if (annotation != null && annotation.read()) {
                //类路径  方法参数  方法名 生成redis key
                StringBuilder builder = new StringBuilder(point.getTarget().getClass().getName())
                        .append(JSON.toJSONString(point.getArgs()))
                        .append(point.getSignature().getName());
                String key = builder.toString();
                Object o = redisTemplate.opsForValue().get(key);
                if (o == null) {
                    // Redis 中不存在，则从数据库中查找，并保存到 Redis
                    log.info("<====== Redis 中不存在该记录，从数据库查找 ======>");
                    o = point.proceed();
                    if (o != null) {
                        //取到了数据哦，放进redis数据库里面
                        if (annotation.expired() > 0) {
                            redisTemplate.opsForValue().set(key, o, annotation.expired(), TimeUnit.SECONDS);
                        } else {
                            redisTemplate.opsForValue().set(key, o);
                        }

                    }

                }
                //返回查询的数据
                return o;

            }
        } catch (Throwable throwable) {
            log.error("<====== RedisCache 执行异常: {} ======>", throwable);
        }
        return null;

    }


}
